package com.example.service.impl;

import com.example.dao.UserDao;
import com.example.entity.User;
import com.example.service.UserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.List;

/**
 * 用户服务实现类
 * @author System
 * @date 2024
 */
@Service
@Transactional
public class UserServiceImpl implements UserService {
    
    private static final Logger logger = LoggerFactory.getLogger(UserServiceImpl.class);
    
    @Autowired
    private UserDao userDao;
    
    @Override
    public boolean register(User user) {
        try {
            // 参数验证
            if (user == null || !StringUtils.hasText(user.getUsername()) || 
                !StringUtils.hasText(user.getPassword()) || !StringUtils.hasText(user.getEmail())) {
                logger.warn("注册参数不完整");
                return false;
            }
            
            // 检查用户名是否已存在
            if (isUsernameExists(user.getUsername())) {
                logger.warn("用户名已存在: {}", user.getUsername());
                return false;
            }
            
            // 检查邮箱是否已存在
            if (isEmailExists(user.getEmail())) {
                logger.warn("邮箱已存在: {}", user.getEmail());
                return false;
            }
            
            // 密码加密
            user.setPassword(encryptPassword(user.getPassword()));
            user.setStatus(1); // 默认启用
            user.setCreateTime(new Date());
            user.setUpdateTime(new Date());
            
            int result = userDao.insert(user);
            logger.info("用户注册成功: {}", user.getUsername());
            return result > 0;
        } catch (Exception e) {
            logger.error("用户注册失败", e);
            return false;
        }
    }
    
    @Override
    @Transactional(readOnly = true)
    public User login(String username, String password) {
        try {
            if (!StringUtils.hasText(username) || !StringUtils.hasText(password)) {
                return null;
            }
            
            User user = userDao.selectByUsername(username);
            if (user == null) {
                logger.warn("用户不存在: {}", username);
                return null;
            }
            
            if (user.getStatus() != 1) {
                logger.warn("用户已被禁用: {}", username);
                return null;
            }
            
            if (validatePassword(user, password)) {
                logger.info("用户登录成功: {}", username);
                // 清除密码信息
                user.setPassword(null);
                return user;
            } else {
                logger.warn("密码错误: {}", username);
                return null;
            }
        } catch (Exception e) {
            logger.error("用户登录失败", e);
            return null;
        }
    }
    
    @Override
    @Transactional(readOnly = true)
    public User getUserById(Long id) {
        try {
            if (id == null || id <= 0) {
                return null;
            }
            User user = userDao.selectById(id);
            if (user != null) {
                user.setPassword(null); // 清除密码信息
            }
            return user;
        } catch (Exception e) {
            logger.error("查询用户失败: id={}", id, e);
            return null;
        }
    }
    
    @Override
    @Transactional(readOnly = true)
    public User getUserByUsername(String username) {
        try {
            if (!StringUtils.hasText(username)) {
                return null;
            }
            User user = userDao.selectByUsername(username);
            if (user != null) {
                user.setPassword(null); // 清除密码信息
            }
            return user;
        } catch (Exception e) {
            logger.error("查询用户失败: username={}", username, e);
            return null;
        }
    }
    
    @Override
    @Transactional(readOnly = true)
    public List<User> getAllUsers() {
        try {
            List<User> users = userDao.selectAll();
            // 清除密码信息
            users.forEach(user -> user.setPassword(null));
            return users;
        } catch (Exception e) {
            logger.error("查询所有用户失败", e);
            return null;
        }
    }
    
    @Override
    @Transactional(readOnly = true)
    public List<User> getUsersByPage(int page, int size) {
        try {
            if (page < 1 || size < 1) {
                return null;
            }
            int offset = (page - 1) * size;
            List<User> users = userDao.selectByPage(offset, size);
            // 清除密码信息
            users.forEach(user -> user.setPassword(null));
            return users;
        } catch (Exception e) {
            logger.error("分页查询用户失败: page={}, size={}", page, size, e);
            return null;
        }
    }
    
    @Override
    @Transactional(readOnly = true)
    public List<User> searchUsers(String keyword) {
        try {
            if (!StringUtils.hasText(keyword)) {
                return getAllUsers();
            }
            List<User> users = userDao.selectByKeyword(keyword);
            // 清除密码信息
            users.forEach(user -> user.setPassword(null));
            return users;
        } catch (Exception e) {
            logger.error("搜索用户失败: keyword={}", keyword, e);
            return null;
        }
    }
    
    @Override
    @Transactional(readOnly = true)
    public int getUserCount() {
        try {
            return userDao.countAll();
        } catch (Exception e) {
            logger.error("统计用户数量失败", e);
            return 0;
        }
    }
    
    @Override
    public boolean updateUser(User user) {
        try {
            if (user == null || user.getId() == null) {
                return false;
            }
            user.setUpdateTime(new Date());
            int result = userDao.update(user);
            logger.info("更新用户信息成功: id={}", user.getId());
            return result > 0;
        } catch (Exception e) {
            logger.error("更新用户信息失败", e);
            return false;
        }
    }
    
    @Override
    public boolean updateUserStatus(Long id, Integer status) {
        try {
            if (id == null || status == null) {
                return false;
            }
            int result = userDao.updateStatus(id, status);
            logger.info("更新用户状态成功: id={}, status={}", id, status);
            return result > 0;
        } catch (Exception e) {
            logger.error("更新用户状态失败: id={}, status={}", id, status, e);
            return false;
        }
    }
    
    @Override
    public boolean changePassword(Long id, String oldPassword, String newPassword) {
        try {
            if (id == null || !StringUtils.hasText(oldPassword) || !StringUtils.hasText(newPassword)) {
                return false;
            }
            
            User user = userDao.selectById(id);
            if (user == null || !validatePassword(user, oldPassword)) {
                logger.warn("旧密码验证失败: id={}", id);
                return false;
            }
            
            String encryptedPassword = encryptPassword(newPassword);
            int result = userDao.updatePassword(id, encryptedPassword);
            logger.info("修改密码成功: id={}", id);
            return result > 0;
        } catch (Exception e) {
            logger.error("修改密码失败: id={}", id, e);
            return false;
        }
    }
    
    @Override
    public boolean resetPassword(Long id, String newPassword) {
        try {
            if (id == null || !StringUtils.hasText(newPassword)) {
                return false;
            }
            
            String encryptedPassword = encryptPassword(newPassword);
            int result = userDao.updatePassword(id, encryptedPassword);
            logger.info("重置密码成功: id={}", id);
            return result > 0;
        } catch (Exception e) {
            logger.error("重置密码失败: id={}", id, e);
            return false;
        }
    }
    
    @Override
    public boolean deleteUser(Long id) {
        try {
            if (id == null || id <= 0) {
                return false;
            }
            int result = userDao.deleteById(id);
            logger.info("删除用户成功: id={}", id);
            return result > 0;
        } catch (Exception e) {
            logger.error("删除用户失败: id={}", id, e);
            return false;
        }
    }
    
    @Override
    public boolean deleteUsers(List<Long> ids) {
        try {
            if (ids == null || ids.isEmpty()) {
                return false;
            }
            int result = userDao.deleteByIds(ids);
            logger.info("批量删除用户成功: count={}", result);
            return result > 0;
        } catch (Exception e) {
            logger.error("批量删除用户失败", e);
            return false;
        }
    }
    
    @Override
    @Transactional(readOnly = true)
    public boolean isUsernameExists(String username) {
        try {
            if (!StringUtils.hasText(username)) {
                return false;
            }
            return userDao.selectByUsername(username) != null;
        } catch (Exception e) {
            logger.error("检查用户名是否存在失败: username={}", username, e);
            return false;
        }
    }
    
    @Override
    @Transactional(readOnly = true)
    public boolean isEmailExists(String email) {
        try {
            if (!StringUtils.hasText(email)) {
                return false;
            }
            return userDao.selectByEmail(email) != null;
        } catch (Exception e) {
            logger.error("检查邮箱是否存在失败: email={}", email, e);
            return false;
        }
    }
    
    @Override
    @Transactional(readOnly = true)
    public boolean validatePassword(User user, String password) {
        if (user == null || !StringUtils.hasText(password) || !StringUtils.hasText(user.getPassword())) {
            return false;
        }
        String encryptedPassword = encryptPassword(password);
        return encryptedPassword.equals(user.getPassword());
    }
    
    /**
     * 密码加密
     * @param password 原始密码
     * @return 加密后的密码
     */
    private String encryptPassword(String password) {
        return DigestUtils.md5DigestAsHex((password + "salt").getBytes());
    }
}